(function ($) {
	$.iosParallax = function (el, options) {
		// To avoid scope issues, use 'base' instead of 'this'
		// to reference this class from internal events and functions.
		var base = this;

		// Access to jQuery and DOM versions of element
		base.$el = $(el);

		// Add a reverse reference to the DOM object
		base.$el.data("iosParallax", base);

		var centerCoordinates = {x: 0, y: 0};
		var targetCoordinates = {x: 0, y: 0};
		var transitionCoordinates = {x: 0, y: 0};
		base.target = targetCoordinates;

		function getBackgroundImageUrl() {
			var backgroundImage = base.$el.css('background-image').match(/url\(.*\)/ig);
			if (!backgroundImage || backgroundImage.length < 1) {
				throw 'No background image found';
			}
			return backgroundImage[0].replace(/url\(|'|"|'|"|\)$/ig, "");
		}

		function getBackgroundImageSize() {
			return {width: base.img.width, height: base.img.height};
		}

		var setCenterCoordinates = function () {
			var bgImgSize = getBackgroundImageSize();
			centerCoordinates.x = -1 * Math.abs(bgImgSize.width - window.innerWidth) / 2;
			centerCoordinates.y = -1 * Math.abs(bgImgSize.height - window.innerHeight) / 2;
			targetCoordinates.x = centerCoordinates.x;
			targetCoordinates.y = centerCoordinates.y;
			transitionCoordinates.x = centerCoordinates.x;
			transitionCoordinates.y = centerCoordinates.y;
		};

		function bindEvents() {
			window.onmousemove = function (e) {
				var width = base.options.movementFactor / window.innerWidth;
				var height = base.options.movementFactor / window.innerHeight;
				var cursorX = e.screenX - ($(window).width() / 2);
				var cursorY = e.screenY - ($(window).height() / 2);
				targetCoordinates.x = width * cursorX * -1 + centerCoordinates.x;
				targetCoordinates.y = height * cursorY * -1 + centerCoordinates.y;
			};

			// Slowly converge the background image position to the target coordinates in 60 FPS
			var loop = setInterval(function () {
				transitionCoordinates.x += ((targetCoordinates.x - transitionCoordinates.x) / base.options.dampenFactor);
				transitionCoordinates.y += ((targetCoordinates.y - transitionCoordinates.y) / base.options.dampenFactor);
				base.$el.css("background-position", transitionCoordinates.x + "px " + transitionCoordinates.y + "px");
			}, 1000 / 40);

			$(window).resize(function () {
				// Re-center the image
				setCenterCoordinates();
			});

			// There's a problem with getting image height and width when the image isn't loaded.
			base.img = new Image;
			base.img.src = getBackgroundImageUrl();
			$(base.img).load(function () {
				setCenterCoordinates();
			});
		};

		base.init = function () {
			base.options = $.extend({}, $.iosParallax.defaultOptions, options);
			bindEvents();
		};

		base.init();
	};

	$.iosParallax.defaultOptions = {
		// How fast the background moves
		movementFactor: 50,
		// How much to dampen the movement (higher is slower)
		dampenFactor: 36
	};

	$.fn.iosParallax = function (options) {
		return this.each(function () {
			(new $.iosParallax(this, options));
		});
	};

})(jQuery);

